package com.rockcent.mall.controller;

import com.rockcent.common.common.JsonResult;
import com.rockcent.common.common.PageResult;
import com.rockcent.common.common.RestDoing;
import com.rockcent.common.controller.BaseController;
import com.rockcent.common.utils.RBeanUtils;
import com.rockcent.mall.Routes;
import com.rockcent.mall.lib.domain.*;
import com.rockcent.mall.lib.domain.enumclass.MerchantFundFlowTransactionType;
import com.rockcent.mall.lib.dto.*;
import com.rockcent.mall.lib.helper.BaseUserHelper;
import com.rockcent.mall.lib.repository.*;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Created by DK on 16/11/8.
 */
@RestController
public class MerchantFundFlowController extends BaseController {
    private final Logger log = LoggerFactory.getLogger(MerchantFundFlowController.class);

    @Autowired
    private BaseUserHelper userHelper;

    @Autowired
    private MerchantFundRepository merchantFundRepository;

    @Autowired
    private MerchantFundFlowRepository merchantFundFlowRepository;

    @Autowired
    private MerchantOrderItemRepository merchantOrderItemRepository;

    @Autowired
    private MerchantWithdrawRepository merchantWithdrawRepository;

    @Autowired
    private MerchantRechargeFlowRepository merchantRechargeFlowRepository;

    @Autowired
    private MerchantOrderRepository merchantOrderRepository;
    /**
     * @api {get} /merchant/fund/info 我的资金 账户余额
     * @apiGroup MERCHANT_FUND
     * @apiVersion 1.0.0
     * @apiHeader {String} userToken 用户token
     * @apiHeader {String} domain 请求域名
     * @apiSuccess {Date} dateCreated 创建时间
     * @apiSuccess {Date} lastUpdated 更新时间
     * @apiSuccess {BigDecimal} totalAmount 总金额
     * @apiSuccess {BigDecimal} frozen 冻结金额
     * @apiSuccess {BigDecimal} availableAmount 可用金额
     * @apiSuccess {BigDecimal} canNotWithdrawAmount 不可提现金额；可提现金额等于可用金额减去不可提现金额
     * @apiSuccess {Long} mallId 平台ID
     * @apiSuccess {Long} merchantId 商家ID
     * @apiSuccessExample {json} Success-Response:
     * {
     *     "code":"1",
     *     "desc":"成功",
     *     "data":{
     *         "lastUpdated":"2016-08-11 16:27:32",
     *         "dateCreated":"2016-08-11 16:27:32",
     *         "totalAmount":3242,
     *         "frozen":222,
     *         "availableAmount":288,
     *         "canNotWithdrawAmount":10,
     *         "merchantId":1,
     *         "mallId":1
     *     }
     * }
     */
    @RequestMapping(value = Routes.MERCHANT_FUND_INFO, method = RequestMethod.GET)
    public JsonResult merchantFundInfo(HttpServletRequest request) {
        UserInfoDto userDto = userHelper.getSession(request);
        RestDoing doing = jsonResult -> {
            MerchantFund merchantFund = merchantFundRepository.findByMallIdAndMerchantId(userDto.mall.getId(), userDto.merchant.getId());
            merchantFund.setAvailableAmount(merchantFund.getAvailableAmount().setScale(2, BigDecimal.ROUND_DOWN));
            jsonResult.data = merchantFund;
        };
        return doing.go(request, log);
    }

    /**
     * @api {get} /merchant/fund/flow/page 我的资金 收支明细 分页
     * @apiGroup MERCHANT_FUND
     * @apiVersion 1.0.0
     * @apiHeader {String} userToken 用户token
     * @apiHeader {String} domain 请求域名
     * @apiParam {String=ALL("全部"),INCOME("收入"),EXPEND("支出")} transactionFlow  <code>必传参数</code> 收支类型 默认ALL
     * @apiParam {String=ALL("全部"), A_ORDER_SETTLEMENT_INCOME("自营收入"),A_ORDER_RESELL_FEE_INCOME("分销收入”), A_RECHARGE_INCOME("普通充值"), A_RECHARGE_PRESENTED("充值赠送”), A_APPLY_WITHDRAW_EXPEND(“提现记录"), A_MERCHANT_SERVICE_FEE_EXPEND(“服务扣费”),MERCHANT_SERVICE_FEE_INCOME("商户基础服务费")} transactionType <code>必传参数</code> 收支类型
     * @apiParam {String} merchantOrderNum 订单号
     * @apiParam {Date} beginDate 开始时间
     * @apiParam {Date} endDate 结束时间
     * @apiSuccess {Date} dateCreated 创建时间
     * @apiSuccess {Date} lastUpdated 更新时间
     * @apiSuccess {BigDecimal} totalAmount 总金额
     * @apiSuccess {BigDecimal} operationAmount 操作金额
     * @apiSuccess {String} merchantOrderNum 商家订单号
     * @apiSuccess {String=ALL("全部"), A_ORDER_SETTLEMENT_INCOME("自营收入"),A_ORDER_RESELL_FEE_INCOME("分销收入”), A_RECHARGE_INCOME("普通充值"), A_RECHARGE_PRESENTED("充值赠送”), A_APPLY_WITHDRAW_EXPEND(“提现记录"), A_MERCHANT_SERVICE_FEE_EXPEND(“服务扣费”),MERCHANT_SERVICE_FEE_INCOME("商户基础服务费")} transactionType 交易类型
     * @apiSuccess {Long} mallId 平台ID
     * @apiSuccess {Long} merchantId 商家ID
     * @apiSuccessExample {json} Success-Response:
     * {
     *     "code":"1",
     *     "desc":"成功",
     *     "data":{
     *         "lastUpdated":"2016-08-11 16:27:32",
     *         "dateCreated":"2016-08-11 16:27:32",
     *         "totalAmount":3242,
     *         "operationAmount":3242,
     *         "merchantOrderNum":234234324234234,
     *         "merchantId":1,
     *         "transactionType":"A_ORDER_SETTLEMENT_INCOME",
     *         "mallId":1
     *     }
     * }
     */
    @RequestMapping(value = Routes.MERCHANT_FUND_FLOW_PAGE, method = RequestMethod.GET)
    public JsonResult merchantFundFlowPage(HttpServletRequest request, MerchantFundFlowDto dto) {
        UserInfoDto userDto = userHelper.getSession(request);
        RestDoing doing = jsonResult -> {
            if (StringUtils.isBlank(dto.getTransactionFlow())) {
                jsonResult.remind("交易类型 不能为空",log);
                return;
            }
            if (StringUtils.isBlank(dto.getTransactionType())) {
                jsonResult.remind("收支种类 不能为空",log);
                return;
            }

            PageResult<MerchantFundFlowDto> pageResult = merchantFundFlowRepository.findMerchantFundFlowPage(dto.getTransactionFlow(), dto.getTransactionType(), dto.getMerchantOrderNum(), dto.getPayType(), dto.getBeginDate(), dto.getEndDate(), userDto.merchant.getId(), userDto.mall.getId(), this.getPage(dto.getPageNo(), dto.getPageSize()));
            pageResult.data.stream().map(merchantFundFlowDto -> {
//                log.info("======================>merchantFundFlowDto:{}", merchantFundFlowDto);

                Long id = merchantFundFlowDto.getId();
                MerchantFundFlowTransactionType fundFlowTransactionType = MerchantFundFlowTransactionType.valueOf(merchantFundFlowDto.getTransactionType());
                if (MerchantFundFlowTransactionType.A_ORDER_RESELL_FEE_INCOME == fundFlowTransactionType) {
                    id = merchantFundFlowDto.getParentId();
                }
                List<MerchantFundFlow> merchantFundFlowList = merchantFundFlowRepository.findByParentIdAndMerchantIdAndMallIdAndMerchantOrderNumOrderByDateCreatedDesc(id, merchantFundFlowDto.getMerchantId(), merchantFundFlowDto.getMallId(), merchantFundFlowDto.getMerchantOrderNum());
                if (MerchantFundFlowTransactionType.A_ORDER_SETTLEMENT_INCOME == fundFlowTransactionType) {
                    merchantFundFlowList.stream().filter(fundFlow -> {
                        MerchantFundFlowTransactionType transactionType = fundFlow.getTransactionType();
                        return MerchantFundFlowTransactionType.A_ORDER_SETTLEMENT_INCOME != transactionType && MerchantFundFlowTransactionType.A_ORDER_SERVICE_FEE_ARREARS_EXPEND != transactionType;
                    }).forEach(fundFlow -> {
//                        log.info("======================>fundFlow 供应商:{}", fundFlow);
                        if (MerchantFundFlowTransactionType.A_ORDER_SETTLEMENT_INCOME == fundFlowTransactionType) {
                            merchantFundFlowDto.setOperationAmount(merchantFundFlowDto.getOperationAmount().subtract(fundFlow.getOperationAmount()));
                        }
                        if (MerchantFundFlowTransactionType.A_ORDER_RESELL_FEE_EXPEND == fundFlow.getTransactionType() || MerchantFundFlowTransactionType.A_ORDER_SERVICE_FEE_EXPEND == fundFlow.getTransactionType() || MerchantFundFlowTransactionType.A_ORDER_SHARE_FEE_EXPEND == fundFlow.getTransactionType()) {
                            if (new BigDecimal(merchantFundFlowDto.getTotalAmount()).compareTo(fundFlow.getTotalAmount()) > 0) {
                                merchantFundFlowDto.setTotalAmount(Double.valueOf(fundFlow.getTotalAmount().toString()));
                            }
                        }

                    });
                } else if (MerchantFundFlowTransactionType.A_ORDER_RESELL_FEE_INCOME == fundFlowTransactionType) {
                    merchantFundFlowList.stream().filter(fundFlow -> {
                        MerchantFundFlowTransactionType transactionType = fundFlow.getTransactionType();
                        return MerchantFundFlowTransactionType.A_ORDER_SHARE_FEE_EXPEND == transactionType || MerchantFundFlowTransactionType.A_ORDER_RESELL_FEE_INCOME == transactionType;
                    }).forEach(fundFlow -> {
//                        log.info("======================>fundFlow 分销商:{}", fundFlow);
//                        log.info("======================>fundFlow.getId():{}, merchantFundFlowDto.getId():{}", fundFlow.getId(), merchantFundFlowDto.getId());
                        MerchantFundFlowTransactionType transactionType = fundFlow.getTransactionType();
                        if (MerchantFundFlowTransactionType.A_ORDER_RESELL_FEE_INCOME == transactionType && !fundFlow.getId().equals(merchantFundFlowDto.getId())){
                            merchantFundFlowDto.setOperationAmount(merchantFundFlowDto.getOperationAmount().add(fundFlow.getOperationAmount()));
                        } else if (MerchantFundFlowTransactionType.A_ORDER_SHARE_FEE_EXPEND == transactionType) {
                            merchantFundFlowDto.setOperationAmount(merchantFundFlowDto.getOperationAmount().subtract(fundFlow.getOperationAmount()));

                        }
                    });
                }
                return merchantFundFlowDto;
            }).collect(Collectors.toList());
            pageResult.setUrl(Routes.MERCHANT_FUND_FLOW_PAGE);
            jsonResult.data = pageResult;
        };
        return doing.go(request, log);
    }

    /**
     * @api {get} /merchant/fund/flow/info 我的资金 收支明细 详情
     * @apiGroup MERCHANT_FUND
     * @apiVersion 1.0.0
     * @apiHeader {String} userToken 用户token
     * @apiHeader {String} domain 请求域名
     * @apiParam {String} id <code>必传参数</code> 资金流水ID
     * @apiSuccess {Date} dateCreated 结算时间
     * @apiSuccess {Date} lastUpdated 更新时间
     * @apiSuccess {BigDecimal} operationAmount 实收金额
     * @apiSuccess {Double} resellExpend 佣金支出
     * @apiSuccess {String= INCOME("收入"), EXPEND("支出")} transactionFlow 类型
     * @apiSuccess {String=ONLINE("线上支付"), OUTLINE("线下支付"),BASE_SERVICE_PAYMENTS("基础服务费扣费"), RECHARGE_MALL("平台支付")} payType 支付类型
     * @apiSuccess {Double} shareExpend 分享支出
     * @apiSuccess {Double} serveExpend 平台服务费支出
     * @apiSuccess {Double} disShareFee 供应商分享支出
     * @apiSuccess {Double} settledFee 已结算金额
     * @apiSuccess {Double} balancePayedFee 余额支付
     * @apiSuccess {String} merchantOrderNum 商家订单号
     * @apiSuccess {String=ALL("全部"), A_ORDER_SETTLEMENT_INCOME("自营收入"),A_ORDER_RESELL_FEE_INCOME("分销收入”), A_RECHARGE_INCOME("普通充值"), A_RECHARGE_PRESENTED("充值赠送”), A_APPLY_WITHDRAW_EXPEND(“提现记录"), A_MERCHANT_SERVICE_FEE_EXPEND(“基础服务费扣费”),A_ORDER_SERVICE_FEE_EXPEND("平台服务费")} transactionType 交易类型
     * @apiSuccess {Long} mallId 平台ID
     * @apiSuccess {Long} merchantId 商家ID
     * @apiSuccess {Long} settlementRecordDtoList_productId 产品编号
     * @apiSuccess {String} settlementRecordDtoList_productName 产品名称
     * @apiSuccess {double} settlementRecordDtoList_serveRate 平台服务费率
     * @apiSuccess {double} settlementRecordDtoList_baseAmount 标准价格
     * @apiSuccess {double} settlementRecordDtoList_singleAmount 实际价格
     * @apiSuccess {Long} settlementRecordDtoList_verifyCount 核销数
     * @apiSuccess {boolean} settlementRecordDtoList_resellFee 佣金率
     * @apiSuccess {String=YES("是"), NO("否")} settlementRecordDtoList_productRefundable 是否可退
     * @apiSuccessExample {json} Success-Response:
     * {
     *     "code":"1",
     *     "desc":"成功",
     *     "data":{
     *         "lastUpdated":"2016-08-11 16:27:32",
     *         "dateCreated":"2016-08-11 16:27:32",
     *         "totalAmount":3242,
     *         "operationAmount":3242,
     *         "merchantOrderNum":234234324234234,
     *         "merchantId":1,
     *         "transactionType":"A_ORDER_SETTLEMENT_INCOME",
     *         "payType":"OUTLINE",
     *         "transactionFlow":"INCOME",
     *         "mallId":1,
     *         "merchantOrderItemList":[
     *             {
     *                 "productId":20,
     *                 "productName":"傻了么",
     *                 "baseAmount":4343,
     *                 "resellFee":345,
     *                 "singleAmount":345,
     *                 "servRate":6%,
     *                 "productRefundable":'YES'
     *             }
     *         ]
     *     }
     * }
     *
     *
     *
     */
    @RequestMapping(value = Routes.MERCHANT_FUND_FLOW_INFO, method = RequestMethod.GET)
    public JsonResult merchantFundFlowInfo(HttpServletRequest request, MerchantFundFlowDto dto) {
        RestDoing doing = jsonResult -> {
            if (dto.getId() == null) {
                jsonResult.remind("资金流水ID 不能为空",log);
                return;
            }

            MerchantFundFlow merchantFundFlow = merchantFundFlowRepository.findOne(dto.getId());
            RBeanUtils.copyProperties(merchantFundFlow, dto);
            MerchantFundFlowTransactionType merchantFundFlowTransactionType = merchantFundFlow.getTransactionType();
            dto.setTransactionType(merchantFundFlowTransactionType.toString());
            dto.setTransactionFlow(merchantFundFlow.getTransactionFlow().toString());
            if (merchantFundFlow.getPayType() != null) {
                dto.setPayType(merchantFundFlow.getPayType().toString());
            }
            String merchantOrderNum = merchantFundFlow.getMerchantOrderNum();
//            log.info("merchantFundFlow：{}",merchantFundFlow);
//            MerchantOrder merchantOrder =merchantOrderRepository.findByOrderNumAndMerchantIdAndMallId(merchantOrderNum,merchantFundFlow.getMerchantId(),merchantFundFlow.getMallId());
//            log.info("merchantFundFlow：{}",merchantFundFlow);

            //自营、分销收入
            BigDecimal income = BigDecimal.valueOf(0);
            BigDecimal shareExpend = BigDecimal.valueOf(0);
            BigDecimal resellExpend = BigDecimal.valueOf(0);
            BigDecimal serveExpend = BigDecimal.valueOf(0);
            BigDecimal disShareFee = BigDecimal.valueOf(0);
            BigDecimal settledFee = BigDecimal.valueOf(0);
            BigDecimal balancePayedFee = merchantFundFlow.getOperationAmount();
            if (MerchantFundFlowTransactionType.A_ORDER_RESELL_FEE_INCOME == merchantFundFlowTransactionType || MerchantFundFlowTransactionType.A_ORDER_SERVICE_FEE_ARREARS_EXPEND == merchantFundFlowTransactionType) {
                merchantFundFlow.setId(merchantFundFlow.getParentId());
            }
            if (MerchantFundFlowTransactionType.A_ORDER_SETTLEMENT_INCOME == merchantFundFlowTransactionType || MerchantFundFlowTransactionType.A_ORDER_RESELL_FEE_INCOME == merchantFundFlowTransactionType || MerchantFundFlowTransactionType.A_ORDER_SERVICE_FEE_ARREARS_EXPEND == merchantFundFlowTransactionType) {
                List<MerchantFundFlow> merchantFundFlowList = merchantFundFlowRepository.findByParentIdAndMerchantIdAndMallIdAndMerchantOrderNum(merchantFundFlow.getId(), merchantFundFlow.getMerchantId(), merchantFundFlow.getMallId(), merchantOrderNum);

                for (MerchantFundFlow fundFlow : merchantFundFlowList) {
//                    log.info("------------------------->fundFlow:{}", fundFlow);
                    MerchantFundFlowTransactionType transactionType = fundFlow.getTransactionType();
                    if (MerchantFundFlowTransactionType.A_ORDER_SERVICE_FEE_EXPEND == transactionType) {
                        serveExpend = serveExpend.add(fundFlow.getOperationAmount());
                    }
                    if (MerchantFundFlowTransactionType.A_ORDER_SETTLEMENT_INCOME == transactionType || MerchantFundFlowTransactionType.A_ORDER_RESELL_FEE_INCOME == transactionType) {
                        income = income.add(fundFlow.getOperationAmount());
                    }
                    if (MerchantFundFlowTransactionType.A_ORDER_RESELL_FEE_EXPEND == transactionType) {
                        resellExpend = resellExpend.add(fundFlow.getOperationAmount());
                    }
                    if (MerchantFundFlowTransactionType.A_ORDER_SHARE_FEE_EXPEND == transactionType) {
                        shareExpend = shareExpend.add(fundFlow.getOperationAmount());
                    }

                    if (MerchantFundFlowTransactionType.A_ORDER_SETTLEMENT_INCOME == merchantFundFlowTransactionType && MerchantFundFlowTransactionType.A_ORDER_SHARE_FEE_EXPEND == transactionType) {
                        disShareFee = disShareFee.add(fundFlow.getOperationAmount());
                    }
                }

//                log.info("------------------------->serveExpend:{},income:{},resellExpend:{},shareExpend:{},disShareFee:{}", serveExpend, income, resellExpend, shareExpend, disShareFee);

                List<MerchantOrderItem> merchantOrderItemList = merchantOrderItemRepository.findByMerchantOrderNumAndMerchantIdAndMallId(merchantOrderNum, merchantFundFlow.getMerchantId(), merchantFundFlow.getMallId());

                if(MerchantFundFlowTransactionType.A_ORDER_SERVICE_FEE_ARREARS_EXPEND == merchantFundFlowTransactionType){
                    serveExpend = new BigDecimal(0l);
                    for (MerchantOrderItem merchantOrderItem : merchantOrderItemList) {
                        BigDecimal singleItemServiceFee = merchantOrderItem.getDiscountAmount().multiply(new BigDecimal(merchantOrderItem.getServeRate())).divide(BigDecimal.valueOf(100L));
//                        log.info("------------------------->singleItemServiceFee:{}", singleItemServiceFee);
                        serveExpend = serveExpend.add(singleItemServiceFee);
                    }
                }



                settledFee = new BigDecimal(Math.abs(balancePayedFee.subtract(serveExpend).doubleValue())).setScale(2, BigDecimal.ROUND_HALF_UP);
//                log.info("------------------------->serveExpend:{},income:{},resellExpend:{},shareExpend:{},disShareFee:{}", serveExpend, income, resellExpend, shareExpend, disShareFee);

                dto.setSettledFee(settledFee);
                dto.setBalancePayedFee(balancePayedFee);
                dto.setOperationAmount(income);
                dto.setResellExpend(Double.valueOf(resellExpend.toString()));
                dto.setServeExpend(Double.valueOf(serveExpend.toString()));
                dto.setShareExpend(Double.valueOf(shareExpend.toString()));
                dto.setDisShareFee(Double.valueOf(disShareFee.toString()));
                dto.setMerchantOrderItemList(merchantOrderItemList);
            }
//            log.info("------------------------->dto:{}", dto);

            //提现
            if (MerchantFundFlowTransactionType.A_APPLY_WITHDRAW_EXPEND == merchantFundFlowTransactionType) {
                MerchantWithdraw merchantWithdraw = merchantWithdrawRepository.findByTransactionIdAndMallId(merchantFundFlow.getMerchantOrderNum(), merchantFundFlow.getMallId());
                dto.setDateCreated(merchantWithdraw.getDateCreated());
                dto.setLastUpdated(merchantWithdraw.getLastUpdated());
            }
            //充值
            if (MerchantFundFlowTransactionType.A_RECHARGE_INCOME == merchantFundFlowTransactionType) {
                MerchantRechargeFlow merchantRechargeFlow = merchantRechargeFlowRepository.findBySeqNoAndMerchantIdAndMallId(merchantFundFlow.getMerchantOrderNum(), merchantFundFlow.getMerchantId(), merchantFundFlow.getMallId());
                dto.setDateCreated(merchantRechargeFlow.getDateCreated());
                dto.setLastUpdated(merchantRechargeFlow.getLastUpdated());
            }
            jsonResult.data = dto;
        };
        return doing.go(request, log);
    }
}
